package com.taldh.algorithm.mutli.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

public class Foo {

    /**
     * 我们提供了一个类：
     *
     * public class Foo {
     *   public void one() { print("one"); }
     *   public void two() { print("two"); }
     *   public void three() { print("three"); }
     * }
     * 三个不同的线程将会共用一个 Foo 实例。
     *
     * 线程 A 将会调用 one() 方法
     * 线程 B 将会调用 two() 方法
     * 线程 C 将会调用 three() 方法
     * 请设计修改程序，以确保 two() 方法在 one() 方法之后被执行，three() 方法在 two() 方法之后被执行。
     *
     * 来源：力扣（LeetCode）
     * 链接：https://leetcode-cn.com/problems/print-in-order
     * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
     */

//    private CountDownLatch secondCountDownLatch = new CountDownLatch(1);
//    private CountDownLatch threeCountDownLatch = new CountDownLatch(1);
//
//    public Foo() {
//    }
//
//    public void first(Runnable printFirst) throws InterruptedException {
//            // printFirst.run() outputs "first". Do not change or remove this line.
//        printFirst.run();
//        secondCountDownLatch.countDown();
//    }
//
//    public void second(Runnable printSecond) throws InterruptedException {
//
//        secondCountDownLatch.await();
//        // printSecond.run() outputs "second". Do not change or remove this line.
//        printSecond.run();
//        threeCountDownLatch.countDown();
//    }
//
//    public void third(Runnable printThird) throws InterruptedException {
//        threeCountDownLatch.await();
//        // printThird.run() outputs "third". Do not change or remove this line.
//        printThird.run();
//    }

    private static volatile int countDown = 3;
    public Foo() {
    }

    public void first(Runnable printFirst) throws InterruptedException {
            // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        countDown -= 1;
    }

    public void second(Runnable printSecond) throws InterruptedException {

        while (countDown >= 2) {
            // printSecond.run() outputs "second". Do not change or remove this line.
            if (countDown == 2) {
                printSecond.run();
                countDown -= 1;
            }
        }
    }

    public void third(Runnable printThird) throws InterruptedException {
        while (countDown >= 1) {
            // printThird.run() outputs "third". Do not change or remove this line.
            if (countDown == 1) {
                printThird.run();
                countDown -= 1;
            }
        }
    }

    public static void main(String[] args) {
        Foo foo = new Foo();
        Runnable runnable = () -> {
            try {
                foo.first(new FooFirst());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Runnable runnable2 = () -> {
            try {
                foo.second(new FooSecond());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Runnable runnable3 = () -> {
            try {
                foo.third(new FooThird());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        new Thread(runnable).start();
        new Thread(runnable2).start();
        new Thread(runnable3).start();
    }
}
